home *** CD-ROM | disk | FTP | other *** search
/ PC World Interactive 7 / PC World Interactive 7.iso / online / gchess.EXE / SEARCH.C < prev    next >
C/C++ Source or Header  |  1995-02-22  |  45KB  |  1,678 lines

  1. /*
  2.   C source for GNU CHESS
  3.  
  4.   Revision: 1990-12-26
  5.  
  6.   Modified by Daryl Baker for use in MS WINDOWS environment
  7.  
  8.   Copyright (C) 1986, 1987, 1988, 1989, 1990 Free Software Foundation, Inc.
  9.   Copyright (c) 1988, 1989, 1990  John Stanback
  10.  
  11.   This file is part of CHESS.
  12.  
  13.   CHESS is distributed in the hope that it will be useful, but WITHOUT ANY
  14.   WARRANTY.  No author or distributor accepts responsibility to anyone for
  15.   the consequences of using it or for whether it serves any particular
  16.   purpose or works at all, unless he says so in writing.  Refer to the CHESS
  17.   General Public License for full details.
  18.  
  19.   Everyone is granted permission to copy, modify and redistribute CHESS, but
  20.   only under the conditions described in the CHESS General Public License.
  21.   A copy of this license is supposed to have been given to you along with
  22.   CHESS so you can know your rights and responsibilities.  It should be in a
  23.   file named COPYING.  Among other things, the copyright notice and this
  24.   notice must be preserved on all copies.
  25. */
  26.  
  27. #define NOATOM 
  28. #define NOCLIPBOARD
  29. #define NOCREATESTRUCT
  30. #define NOFONT
  31. #define NOREGION
  32. #define NOSOUND
  33. #define NOWH
  34. #define NOWINOFFSETS
  35. #define NOCOMM
  36. #define NOKANJI
  37.  
  38. #include <windows.h>
  39. #include <windowsx.h>
  40. #include <string.h>
  41. #include <time.h>
  42. #include <stdlib.h>
  43. #include <malloc.h>
  44. #include <stdio.h>
  45.  
  46. #include "gnuchess.h"
  47. #include "defs.h"
  48.  
  49. #ifdef WIN32
  50. #define _BASEETC
  51. #else
  52. #define _BASEETC _based(_segname("_CODE")) 
  53. #endif
  54.  
  55. #if ttblsz
  56. extern unsigned long hashkey, hashbd;
  57. /*extern struct hashval hashcode[2][7][64];*/
  58. /*extern struct hashentry huge ttable[2][ttblsz];*/
  59. extern struct hashval far *hashcode;
  60. extern struct hashentry far *ttable;
  61. #endif /* ttblsz */
  62.  
  63. /*extern unsigned char history[8192];*/
  64. extern unsigned char far * history;
  65.  
  66. extern short rpthash[2][256];
  67. /*extern unsigned char nextpos[8][64][64];*/
  68. /*extern unsigned char nextdir[8][64][64];*/
  69. extern unsigned char far *nextpos;
  70. extern unsigned char far *nextdir;
  71.  
  72. extern short FROMsquare, TOsquare, Zscore, zwndw;
  73. extern unsigned short PV, Swag0, Swag1, Swag2, Swag3, Swag4;
  74. extern unsigned short killr0[maxdepth], killr1[maxdepth];
  75. extern unsigned short killr2[maxdepth], killr3[maxdepth];
  76. extern short Pscore[maxdepth], Tscore[maxdepth];
  77. extern unsigned long hashkey, hashbd;
  78. extern short ChkFlag[maxdepth], CptrFlag[maxdepth], PawnThreat[maxdepth];
  79. extern short mtl[2], pmtl[2], emtl[2], hung[2];
  80. extern short player, xwndw, rehash;
  81. extern short PieceCnt[2];
  82. extern long NodeCnt, ETnodes, EvalNodes, HashCnt, FHashCnt, HashCol;
  83. extern short HasKnight[2], HasBishop[2], HasRook[2], HasQueen[2];
  84. extern short Pindex[64];
  85.  
  86. static short _BASEETC rank7[3] = {6, 1, 0};
  87. static short _BASEETC kingP[3] = {4, 60, 0};
  88. static short _BASEETC value[7] =
  89. {0, valueP, valueN, valueB, valueR, valueQ, valueK};
  90.  
  91. static short _BASEETC sweep[8] =
  92. {false, false, false, true, true, true, false, false};
  93.  
  94. static short _BASEETC ptype[2][8] = {
  95.   no_piece, pawn, knight, bishop, rook, queen, king, no_piece,
  96.   no_piece, bpawn, knight, bishop, rook, queen, king, no_piece};
  97.  
  98. static short _BASEETC control[7] =
  99. {0, ctlP, ctlN, ctlB, ctlR, ctlQ, ctlK};
  100.  
  101. /* ............    MOVE GENERATION & SEARCH ROUTINES    .............. */
  102.  
  103. void
  104. pick (short int p1, short int p2)
  105.  
  106. /*
  107.   Find the best move in the tree between indexes p1 and p2. Swap the best
  108.   move into the p1 element.
  109. */
  110.  
  111. {
  112.   register short p, s;
  113.   short p0, s0;
  114.   struct leaf temp;
  115.  
  116.   s0 = Tree[p1].score;
  117.   p0 = p1;
  118.   for (p = p1 + 1; p <= p2; p++)
  119.     if ((s = Tree[p].score) > s0)
  120.       {
  121.         s0 = s;
  122.         p0 = p;
  123.       }
  124.   if (p0 != p1)
  125.     {
  126.       temp = Tree[p1];
  127.       Tree[p1] = Tree[p0];
  128.       Tree[p0] = temp;
  129.     }
  130. }
  131.  
  132. void
  133. SelectMove (HWND hWnd, short int side, short int iop)
  134.  
  135. /*
  136.   Select a move by calling function search() at progressively deeper ply
  137.   until time is up or a mate or draw is reached. An alpha-beta window of -90
  138.   to +90 points is set around the score returned from the previous
  139.   iteration. If Sdepth != 0 then the program has correctly predicted the
  140.   opponents move and the search will start at a depth of Sdepth+1 rather
  141.   than a depth of 1.
  142. */
  143.  
  144. {
  145.   static short i, tempb, tempc, tempsf, tempst, xside, rpt;
  146.   static short alpha, beta, score;
  147.  
  148.   flag.timeout = false;
  149.   xside = otherside[side];
  150.   if (iop != 2)
  151.     player = side;
  152.   if (TCflag)
  153.     {
  154.       if ((TimeControl.moves[side] + 3) != 0)
  155.         ResponseTime = (TimeControl.clock[side]) /
  156.           (TimeControl.moves[side] + 3) -
  157.           OperatorTime;
  158.       else
  159.         ResponseTime = 0;
  160.       ResponseTime += (ResponseTime * TimeControl.moves[side]) / (2 * TCmoves + 1);
  161.     }
  162.   else
  163.     ResponseTime = Level;
  164.   if (iop == 2)
  165.     ResponseTime = 99999;
  166.   if (Sdepth > 0 && root->score > Zscore - zwndw)
  167.     ResponseTime -= ft;
  168.   else if (ResponseTime < 1)
  169.     ResponseTime = 1;
  170.   ExtraTime = 0;
  171.   ExaminePosition ();
  172.   ScorePosition (side, &score);
  173.   /* Pscore[0] = -score; */
  174.   ShowSidetoMove ();
  175.  
  176.   if (Sdepth == 0)
  177.     {
  178. #if ttblsz
  179.       /* ZeroTTable (); */
  180. #endif /* ttblsz */
  181.       SearchStartStuff (side);
  182. #ifdef NOMEMSET
  183.       for (i = 0; i < 8192; i++)
  184. /*        history[i] = 0; */
  185.           *(history+i) = 0;
  186.  
  187. #else
  188.       _fmemset ( history, 0, 8192 * sizeof (char));
  189. #endif /* NOMEMSET */
  190.       FROMsquare = TOsquare = -1;
  191.       PV = 0;
  192.       if (iop != 2)
  193.         hint = 0;
  194.       for (i = 0; i < maxdepth; i++)
  195.         PrVar[i] = killr0[i] = killr1[i] = killr2[i] = killr3[i] = 0;
  196.       alpha = score - 90;
  197.       beta = score + 90;
  198.       rpt = 0;
  199.       TrPnt[1] = 0;
  200.       root = &Tree[0];
  201.       MoveList (side, 1);
  202.       for (i = TrPnt[1]; i < TrPnt[2]; i++)
  203.         pick (i, TrPnt[2] - 1);
  204.       if (Book != NULL)
  205.         OpeningBook (&hint);
  206.       if (Book != NULL)
  207.         flag.timeout = true;
  208.       NodeCnt = ETnodes = EvalNodes = HashCnt = FHashCnt = HashCol = 0;
  209.       Zscore = 0;
  210.       zwndw = 20;
  211.     }
  212.   while (!flag.timeout && Sdepth < MaxSearchDepth)
  213.     {
  214.       Sdepth++;
  215.       ShowDepth (' ');
  216.       score = search (hWnd, side, 1, Sdepth, alpha, beta, PrVar, &rpt);
  217.       for (i = 1; i <= Sdepth; i++)
  218.         killr0[i] = PrVar[i];
  219.       if (score < alpha)
  220.         {
  221.           ShowDepth ('\xbb' /*'-'*/);
  222.           ExtraTime = 10 * ResponseTime;
  223.           /* ZeroTTable (); */
  224.           score = search (hWnd, side, 1, Sdepth, -9000, score, PrVar, &rpt);
  225.         }
  226.       if (score > beta && !(root->flags & exact))
  227.         {
  228.           ShowDepth ('\xab' /*'+'*/);
  229.           ExtraTime = 0;
  230.           /* ZeroTTable (); */
  231.           score = search (hWnd, side, 1, Sdepth, score, 9000, PrVar, &rpt);
  232.         }
  233.       score = root->score;
  234.       if (!flag.timeout)
  235.         for (i = TrPnt[1] + 1; i < TrPnt[2]; i++)
  236.           pick (i, TrPnt[2] - 1);
  237.       ShowResults (score, PrVar, '\xb7' /*'.'*/);
  238.       for (i = 1; i <= Sdepth; i++)
  239.         killr0[i] = PrVar[i];
  240.       if (score > Zscore - zwndw && score > Tree[1].score + 250)
  241.         ExtraTime = 0;
  242.       else if (score > Zscore - 3 * zwndw)
  243.         ExtraTime = ResponseTime;
  244.       else
  245.         ExtraTime = 3 * ResponseTime;
  246.       if (root->flags & exact)
  247.         flag.timeout = true;
  248.       if (Tree[1].score < -9000)
  249.         flag.timeout = true;
  250.       if (4 * et > 2 * ResponseTime + ExtraTime)
  251.         flag.timeout = true;
  252.       if (!flag.timeout)
  253.         {
  254.           Tscore[0] = score;
  255.           if (Zscore == 0)
  256.             Zscore = score;
  257.           else
  258.             Zscore = (Zscore + score) / 2;
  259.         }
  260.       zwndw = 20 + abs (Zscore / 12);
  261.       beta = score + Bwindow;
  262.       if (Zscore < score)
  263.         alpha = Zscore - Awindow - zwndw;
  264.       else
  265.         alpha = score - Awindow - zwndw;
  266.     }
  267.  
  268.   score = root->score;
  269.   if (rpt >= 2 || score < -12000)
  270.     root->flags |= draw;
  271.   if (iop == 2)
  272.     return;
  273.   if (Book == NULL)
  274.     hint = PrVar[2];
  275.   ElapsedTime (1);
  276.  
  277.   if (score > -9999 && rpt <= 2)
  278.     {
  279.       MakeMove (side, root, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  280.       algbr (root->f, root->t, (short) root->flags);
  281.     }
  282.   else
  283.     algbr (0, 0, 0);
  284.   OutputMove (hWnd);
  285.   if (score == -9999 || score == 9998)
  286.     flag.mate = true;
  287.   if (flag.mate)
  288.     hint = 0;
  289.   if ((board[root->t] == pawn)
  290.       || (root->flags & capture)
  291.       || (root->flags & cstlmask))
  292.     {
  293.       Game50 = GameCnt;
  294.       ZeroRPT ();
  295.     }
  296.   GameList[GameCnt].score = score;
  297.   GameList[GameCnt].nodes = NodeCnt;
  298.   GameList[GameCnt].time = (short) et;
  299.   GameList[GameCnt].depth = Sdepth;
  300.   if (TCflag)
  301.     {
  302.       TimeControl.clock[side] -= (et + OperatorTime);
  303.       if (--TimeControl.moves[side] == 0)
  304.         SetTimeControl ();
  305.     }
  306.   if ((root->flags & draw) && flag.bothsides)
  307.     flag.mate = true;
  308.   if (GameCnt > 470)
  309.     flag.mate = true; /* out of move store, you loose */
  310.   player = xside;
  311.   Sdepth = 0;
  312. }
  313.  
  314. int
  315. parse (FILE *fd, short unsigned int *mv, short int side)
  316. {
  317.   int c, i, r1, r2, c1, c2;
  318.   char s[100];
  319.   while ((c = getc (fd)) == ' ') ;
  320.   i = 0;
  321.   s[0] = (char) c;
  322.   while (c != ' ' && c != '\n' && c != EOF)
  323.     s[++i] = (char) (c = getc (fd));
  324.   s[++i] = '\0';
  325.   if (c == EOF)
  326.     return (-1);
  327.   if (s[0] == '!' || s[0] == ';' || i < 3)
  328.     {
  329.       while (c != '\n' && c != EOF)
  330.         c = getc (fd);
  331.       return (0);
  332.     }
  333.   if (s[4] == 'o')
  334.     if (side == black)
  335.       *mv = 0x3C3A;
  336.     else
  337.       *mv = 0x0402;
  338.   else if (s[0] == 'o')
  339.     if (side == black)
  340.       *mv = 0x3C3E;
  341.     else
  342.       *mv = 0x0406;
  343.   else
  344.     {
  345.       c1 = s[0] - 'a';
  346.       r1 = s[1] - '1';
  347.       c2 = s[2] - 'a';
  348.       r2 = s[3] - '1';
  349.       *mv = (locn (r1, c1) << 8) | locn (r2, c2);
  350.     }
  351.   return (1);
  352. }
  353.  
  354. inline void
  355. repetition (short int *cnt)
  356.  
  357. /*
  358.   Check for draw by threefold repetition.
  359. */
  360.  
  361. {
  362.   short i, c, f, t;
  363.   short b[64];
  364.   unsigned short m;
  365.  
  366.   *cnt = c = 0;
  367.   if (GameCnt > Game50 + 3)
  368.     {
  369. #ifdef NOMEMSET
  370.       for (i = 0; i < 64; b[i++] = 0) ;
  371. #else
  372.       memset ((char *) b, 0, sizeof (b));
  373. #endif /* NOMEMSET */
  374.       for (i = GameCnt; i > Game50; i--)
  375.         {
  376.           m = GameList[i].gmove;
  377.           f = m >> 8;
  378.           t = m & 0xFF;
  379.           if (++b[f] == 0)
  380.             c--;
  381.           else
  382.             c++;
  383.           if (--b[t] == 0)
  384.             c--;
  385.           else
  386.             c++;
  387.           if (c == 0)
  388.             (*cnt)++;
  389.         }
  390.     }
  391. }
  392.  
  393. int
  394. search (HWND hWnd,
  395.         short int side,
  396.         short int ply,
  397.         short int depth,
  398.         short int alpha,
  399.         short int beta,
  400.         short unsigned int *bstline,
  401.         short int *rpt)
  402.  
  403. /*
  404.   Perform an alpha-beta search to determine the score for the current board
  405.   position. If depth <= 0 only capturing moves, pawn promotions and
  406.   responses to check are generated and searched, otherwise all moves are
  407.   processed. The search depth is modified for check evasions, certain
  408.   re-captures and threats. Extensions may continue for up to 11 ply beyond
  409.   the nominal search depth.
  410. */
  411.  
  412. #define UpdateSearchStatus \
  413. {\
  414.    if (flag.post) ShowCurrentMove(pnt,node->f,node->t);\
  415.      if (pnt > TrPnt[1])\
  416.        {\
  417.           d = best-Zscore; e = best-node->score;\
  418.             if (best < alpha) ExtraTime = 10*ResponseTime;\
  419.             else if (d > -zwndw && e > 4*zwndw) ExtraTime = -ResponseTime/3;\
  420.             else if (d > -zwndw) ExtraTime = 0;\
  421.             else if (d > -3*zwndw) ExtraTime = ResponseTime;\
  422.             else if (d > -9*zwndw) ExtraTime = 3*ResponseTime;\
  423.             else ExtraTime = 5*ResponseTime;\
  424.             }\
  425.             }
  426. #define prune (cf && score+node->score < alpha)
  427. #define ReCapture (flag.rcptr && score > alpha && score < beta &&\
  428.                    ply > 2 && CptrFlag[ply-1] && CptrFlag[ply-2])
  429. /* && depth == Sdepth-ply+1 */
  430. #define Parry (hung[side] > 1 && ply == Sdepth+1)
  431. #define MateThreat (ply < Sdepth+4 && ply > 4 &&\
  432.                     ChkFlag[ply-2] && ChkFlag[ply-4] &&\
  433.                     ChkFlag[ply-2] != ChkFlag[ply-4])
  434.  
  435. {
  436.   register short j, pnt;
  437.   short best, tempb, tempc, tempsf, tempst;
  438.   short xside, pbst, d, e, cf, score, rcnt, slk, InChk;
  439.   unsigned short mv, nxtline[maxdepth];
  440.   struct leaf far *node, tmp;
  441.  
  442.   NodeCnt++;
  443.   xside = otherside[side];
  444.  
  445.   if ((ply <= Sdepth + 3) && rpthash[side][hashkey & 0xFF] > 0)
  446.     repetition (rpt);
  447.   else
  448.     *rpt = 0;
  449.   /* Detect repetitions a bit earlier. SMC. 12/89 */
  450.   if (*rpt == 1 && ply > 1)
  451.     return (0);
  452.   /* if (*rpt >= 2) return(0); */
  453.  
  454.   score = evaluate (side, ply, alpha, beta, INCscore, &slk, &InChk);
  455.   if (score > 9000)
  456.     {
  457.       bstline[ply] = 0;
  458.       return (score);
  459.     }
  460.  
  461.       /* This test has been modified in 3.1 from 1.55 code. I think the mods
  462.          have introduced an error in the search which causes the programme
  463.          to run away from checking moves - hence the failure to find mates
  464.          and to play through mate situations.
  465.          The fixes introduced solve the problem reported by:
  466.          cambell@rnd.GBA.NYU.EDU
  467.          in the mate example.
  468.                                  J.Birmingham.
  469.       */
  470.   if (depth > 0)
  471.     {
  472.       /* Allow opponent a chance to check again */
  473.       if (InChk)
  474.         depth = (depth < 2) ? 2 : depth;
  475.       else if (PawnThreat[ply - 1] || ReCapture)
  476.         ++depth;
  477.     }
  478.   else
  479.     {
  480.       if (score >= alpha &&
  481.           (InChk || PawnThreat[ply - 1] || Parry))
  482.         ++depth;           /* this was depth=1 in original ?bug? */
  483.       else if (score <= beta && MateThreat)
  484.         ++depth;           /* this was also set to depth=1  ?bug? */
  485.     }
  486.  
  487.    /* end of changed section      J.Birmingham.          */
  488.  
  489. #if ttblsz
  490.   if (depth > 0 && flag.hash && ply > 1)
  491.     {
  492.       if (ProbeTTable (side, depth, &alpha, &beta, &score) == false)
  493. #ifdef HASHFILE 
  494.         if (hashfile && (depth > 5) && (GameCnt < 12))
  495.           ProbeFTable (side, depth, &alpha, &beta, &score);
  496. #else
  497.       /* do nothing */;
  498. #endif /* HASHFILE */      
  499.       bstline[ply] = PV;
  500.       bstline[ply + 1] = 0;
  501.       if (beta == -20000)
  502.         return (score);
  503.       if (alpha > beta)
  504.         return (alpha);
  505.     }
  506. #endif /* ttblsz */
  507.   if (Sdepth == 1)
  508.     d = 7;
  509.   else
  510.     d = 11;
  511.   if (ply > Sdepth + d || (depth < 1 && score > beta))
  512.     /* score >= beta ?? */
  513.     return (score);
  514.  
  515.   if (ply > 1)
  516.     if (depth > 0)
  517.       MoveList (side, ply);
  518.     else
  519.       CaptureList (side, ply);
  520.  
  521.   if (TrPnt[ply] == TrPnt[ply + 1])
  522.     return (score);
  523.  
  524.   cf = (depth < 1 && ply > Sdepth + 1 && !ChkFlag[ply - 2] && !slk);
  525.  
  526.   if (depth > 0)
  527.     best = -12000;
  528.   else
  529.     best = score;
  530.   if (best > alpha)
  531.     alpha = best;
  532.  
  533.   for (pnt = pbst = TrPnt[ply];
  534.        pnt < TrPnt[ply + 1] && best <= beta;    /* best < beta ?? */
  535.        pnt++)
  536.     {
  537.  
  538.       /* Little code segment to allow cooperative multitasking */
  539.       {
  540.          MSG msg;
  541.          extern HANDLE hAccel;
  542.          if ( !flag.timeout && PeekMessage(&msg, (HWND)NULL, (UINT)NULL, 
  543.                        (UINT)NULL, PM_REMOVE)){
  544.             if ( !TranslateAccelerator (hWnd, hAccel, &msg) ) {
  545.                TranslateMessage(&msg);
  546.                DispatchMessage(&msg);
  547.             }
  548.          }
  549.       }
  550.       /* End of segment */
  551.  
  552.       if (ply > 1)
  553.         pick (pnt, TrPnt[ply + 1] - 1);
  554.       node = &Tree[pnt];
  555.       mv = (node->f << 8) | node->t;
  556.       nxtline[ply + 1] = 0;
  557.  
  558.       if (prune)
  559.         break;
  560.       if (ply == 1)
  561.         UpdateSearchStatus;
  562.  
  563.       if (!(node->flags & exact))
  564.         {
  565.           MakeMove (side, node, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  566.           CptrFlag[ply] = (node->flags & capture);
  567.           PawnThreat[ply] = (node->flags & pwnthrt);
  568.           Tscore[ply] = node->score;
  569.           PV = node->reply;
  570.           node->score = -search (hWnd, xside, ply + 1,
  571.                                  (depth > 0) ? depth - 1 : 0,
  572.                                  -beta, -alpha,
  573.                                  nxtline, &rcnt);
  574.           if (abs (node->score) > 9000)
  575.             node->flags |= exact;
  576.           else if (rcnt == 1)
  577.             node->score /= 2;
  578.           if (rcnt >= 2 || GameCnt - Game50 > 99 ||
  579.               (node->score == 9999 - ply && !ChkFlag[ply]))
  580.             {
  581.               node->flags |= draw;
  582.               node->flags |= exact;
  583.               if (side == computer)
  584.                 node->score = contempt;
  585.               else
  586.                 node->score = -contempt;
  587.             }
  588.           node->reply = nxtline[ply + 1];
  589.           UnmakeMove (side, node, &tempb, &tempc, &tempsf, &tempst);
  590.         }
  591.       if (node->score > best && !flag.timeout)
  592.         {
  593.           if (depth > 0)
  594.             if (node->score > alpha && !(node->flags & exact))
  595.               node->score += depth;
  596.           best = node->score;
  597.           pbst = pnt;
  598.           if (best > alpha)
  599.             alpha = best;
  600.           for (j = ply + 1; nxtline[j] > 0; j++)
  601.             bstline[j] = nxtline[j];
  602.           bstline[j] = 0;
  603.           bstline[ply] = mv;
  604.           if (ply == 1)
  605.             {
  606.               if (best > root->score)
  607.                 {
  608.                   tmp = Tree[pnt];
  609.                   for (j = pnt - 1; j >= 0; j--)
  610.                     Tree[j + 1] = Tree[j];
  611.                   Tree[0] = tmp;
  612.                   pbst = 0;
  613.                 }
  614.               if (Sdepth > 2)
  615.                 if (best > beta)
  616.                   ShowResults (best, bstline, '\xab' /*'+'*/);
  617.                 else if (best < alpha)
  618.                   ShowResults (best, bstline, '\xbb' /* '-'*/);
  619.                 else
  620.                   ShowResults (best, bstline, '\xb1' /*'&'*/);
  621.             }
  622.         }
  623.       if (NodeCnt > ETnodes)
  624.         ElapsedTime (0);
  625.       if (flag.timeout)
  626.         return (-Tscore[ply - 1]);
  627.     }
  628.  
  629.   node = &Tree[pbst];
  630.   mv = (node->f << 8) | node->t;
  631. #if ttblsz
  632.   if (flag.hash && ply <= Sdepth && *rpt == 0 && best == alpha)
  633.     {
  634.       PutInTTable (side, best, depth, alpha, beta, mv);
  635. #ifdef HASHFILE      
  636.       if (hashfile && (depth > 5) && (GameCnt < 12))
  637.         PutInFTable (side, best, depth, alpha, beta, node->f, node->t);
  638. #endif /* HASHFILE */      
  639.     }
  640. #endif /* ttblsz */
  641.   if (depth > 0)
  642.     {
  643.       j = (node->f << 6) | node->t;
  644.       if (side == black)
  645.         j |= 0x1000;
  646. /*      if (history[j] < 150)
  647.           history[j] += (unsigned char) 2 * depth; */
  648.       if (*(history+j) < 150)
  649.         *(history+j) += (unsigned char) 2 * depth;
  650.       if (node->t != (GameList[GameCnt].gmove & 0xFF))
  651.         if (best <= beta)
  652.           killr3[ply] = mv;
  653.         else if (mv != killr1[ply])
  654.           {
  655.             killr2[ply] = killr1[ply];
  656.             killr1[ply] = mv;
  657.           }
  658.       if (best > 9000)
  659.         killr0[ply] = mv;
  660.       else
  661.         killr0[ply] = 0;
  662.     }
  663.   return (best);
  664. }
  665.  
  666. #if ttblsz
  667. /*
  668.   hashbd contains a 32 bit "signature" of the board position. hashkey
  669.   contains a 16 bit code used to address the hash table. When a move is
  670.   made, XOR'ing the hashcode of moved piece on the from and to squares with
  671.   the hashbd and hashkey values keeps things current.
  672. */
  673. #define UpdateHashbd(side, piece, f, t) \
  674. {\
  675.   if ((f) >= 0)\
  676.     {\
  677.       hashbd ^= (hashcode+(side)*7*64+(piece)*64+f)->bd;\
  678.       hashkey ^= (hashcode+(side)*7*64+(piece)*64+f)->key;\
  679.     }\
  680.   if ((t) >= 0)\
  681.     {\
  682.       hashbd ^= (hashcode+(side)*7*64+(piece)*64+t)->bd;\
  683.       hashkey ^= (hashcode+(side)*7*64+(piece)*64+t)->key;\
  684.     }\
  685. }
  686.  
  687. #define CB(i) (unsigned char) ((color[2 * (i)] ? 0x80 : 0)\
  688.                | (board[2 * (i)] << 4)\
  689.                | (color[2 * (i) + 1] ? 0x8 : 0)\
  690.                | (board[2 * (i) + 1]))
  691.  
  692. int
  693. ProbeTTable (short int side,
  694.              short int depth,
  695.              short int *alpha,
  696.              short int *beta,
  697.              short int *score)
  698.  
  699. /*
  700.   Look for the current board position in the transposition table.
  701. */
  702.  
  703. {
  704.   struct hashentry far *ptbl;
  705.   register unsigned short i;
  706.  
  707. /*  ptbl = &ttable[side][hashkey & (ttblsz - 1)]; */
  708.    ptbl = ttable+side*2+(hashkey & (ttblsz - 1));
  709.  
  710.   /* rehash max rehash times */
  711.   for (i = 1; ptbl->hashbd != hashbd && i <= rehash; i++)
  712. /*    ptbl = &ttable[side][(hashkey + i) & (ttblsz - 1)]; */
  713.     ptbl = ttable+side*2+((hashkey + i) & (ttblsz - 1));
  714.   if ((short) ptbl->depth >= depth && ptbl->hashbd == hashbd)
  715.     {
  716.       HashCnt++;
  717. #ifdef HASHTEST
  718.       for (i = 0; i < 32; i++)
  719.         {
  720.           if (ptbl->bd[i] != CB(i))
  721.             {
  722.               HashCol++;
  723.               ShowMessage("ttable collision detected");
  724.               break;
  725.             }
  726.         }
  727. #endif /* HASHTEST */
  728.  
  729.       PV = ptbl->mv;
  730.       if (ptbl->flags & truescore)
  731.         {
  732.           *score = ptbl->score;
  733.           *beta = -20000;
  734.         }
  735. #if 0 /* commented out, why? */
  736.       else if (ptbl->flags & upperbound)
  737.         {
  738.           if (ptbl->score < *beta) *beta = ptbl->score+1;
  739.         }
  740. #endif
  741.       else if (ptbl->flags & lowerbound)
  742.         {
  743.           if (ptbl->score > *alpha)
  744.             *alpha = ptbl->score - 1;
  745.         }
  746.       return(true);
  747.     }
  748.   return(false);
  749. }
  750.  
  751. void
  752. PutInTTable (short int side,
  753.              short int score,
  754.              short int depth,
  755.              short int alpha,
  756.              short int beta,
  757.              short unsigned int mv)
  758.  
  759. /*
  760.   Store the current board position in the transposition table.
  761. */
  762.  
  763. {
  764.   struct hashentry far *ptbl;
  765.   register unsigned short i;
  766.  
  767. /*  ptbl = &ttable[side][hashkey & (ttblsz - 1)]; */
  768.   ptbl = ttable+side*2+(hashkey & (ttblsz - 1));
  769.  
  770.   /* rehash max rehash times */
  771.   for (i = 1; depth < ptbl->depth && ptbl->hashbd != hashbd && i <= rehash; i++)
  772. /*    ptbl = &ttable[side][(hashkey + i) & (ttblsz - 1)]; */
  773.     ptbl = ttable+side*2+((hashkey + i) & (ttblsz - 1));
  774.   if (depth >= ptbl->depth || ptbl->hashbd != hashbd)
  775.     {
  776.       ptbl->hashbd = hashbd;
  777.       ptbl->depth = (unsigned char) depth;
  778.       ptbl->score = score;
  779.       ptbl->mv = mv;
  780.       ptbl->flags = 0;
  781.       if (score < alpha)
  782.         ptbl->flags |= upperbound;
  783.       else if (score > beta)
  784.         ptbl->flags |= lowerbound;
  785.       else
  786.         ptbl->flags |= truescore;
  787. #ifdef HASHTEST
  788.       for (i = 0; i < 32; i++)
  789.         {
  790.           ptbl->bd[i] = CB(i);
  791.         }
  792. #endif /* HASHTEST */
  793.     }
  794. }
  795.  
  796. void
  797. ZeroTTable (void)
  798. {
  799.   register int side, i;
  800.  
  801.   if (flag.hash)
  802.     for (side = white; side <= black; side++)
  803.       for (i = 0; i < ttblsz; i++)
  804. /*        ttable[side][i].depth = 0; */
  805.         (ttable+side*2+i)->depth = 0;
  806. }
  807.  
  808. #ifdef HASHFILE
  809. int
  810. ProbeFTable(short int side,
  811.             short int depth,
  812.             short int *alpha,
  813.             short int *beta,
  814.             short int *score)
  815.  
  816. /*
  817.   Look for the current board position in the persistent transposition table.
  818. */
  819.  
  820. {
  821.   register unsigned short i, j;
  822.   unsigned long hashix;
  823.   short s;
  824.   struct fileentry new, t;
  825.  
  826.   if (side == white)
  827.     hashix = hashkey & 0xFFFFFFFE & (filesz - 1);
  828.   else
  829.     hashix = hashkey | 1 & (filesz - 1);
  830.  
  831.   for (i = 0; i < 32; i++)
  832.     new.bd[i] = CB(i);
  833.   new.flags = 0;
  834.   if ((Mvboard[kingP[side]] == 0) && (Mvboard[qrook[side]] == 0))
  835.     new.flags |= queencastle;
  836.   if ((Mvboard[kingP[side]] == 0) && (Mvboard[krook[side]] == 0))
  837.     new.flags |= kingcastle;
  838.  
  839.   for (i = 0; i < frehash; i++)
  840.     {
  841.       fseek(hashfile,
  842.             sizeof(struct fileentry) * ((hashix + 2 * i) & (filesz - 1)),
  843.             SEEK_SET);
  844.       fread(&t, sizeof(struct fileentry), 1, hashfile);
  845.       for (j = 0; j < 32; j++)
  846.         if (t.bd[j] != new.bd[j])
  847.           break;
  848.       if (((short) t.depth >= depth) && (j >= 32)
  849.           && (new.flags == (t.flags & (kingcastle | queencastle))))
  850.         {
  851.           FHashCnt++;
  852.           PV = (t.f << 8) | t.t;
  853.           s = (t.sh << 8) | t.sl;
  854.           if (t.flags & truescore)
  855.             {
  856.               *score = s;
  857.               *beta = -20000;
  858.             }
  859.           else if (t.flags & lowerbound)
  860.             {
  861.               if (s > *alpha)
  862.                 *alpha = s - 1;
  863.             }
  864.           return(true);
  865.         }
  866.     }
  867.   return(false);
  868. }
  869.  
  870. void
  871. PutInFTable (short int side,
  872.              short int score,
  873.              short int depth,
  874.              short int alpha,
  875.              short int beta,
  876.              short unsigned int f,
  877.              short unsigned int t)
  878.  
  879. /*
  880.   Store the current board position in the persistent transposition table.
  881. */
  882.  
  883. {
  884.   register unsigned short i;
  885.   unsigned long hashix;
  886.   struct fileentry new, tmp;
  887.  
  888.   if (side == white)
  889.     hashix = hashkey & 0xFFFFFFFE & (filesz - 1);
  890.   else
  891.     hashix = hashkey | 1 & (filesz - 1);
  892.  
  893.   for (i = 0; i < 32; i++)
  894.     new.bd[i] = CB(i);
  895.   new.f = (unsigned char) f;
  896.   new.t = (unsigned char) t;
  897.   new.flags = 0;
  898.   if (score < alpha)
  899.     new.flags |= upperbound;
  900.   else if (score > beta)
  901.     new.flags |= lowerbound;
  902.   else
  903.     new.flags |= truescore;
  904.   if ((Mvboard[kingP[side]] == 0) && (Mvboard[qrook[side]] == 0))
  905.     new.flags |= queencastle;
  906.   if ((Mvboard[kingP[side]] == 0) && (Mvboard[krook[side]] == 0))
  907.     new.flags |= kingcastle;
  908.   new.depth = (unsigned char) depth;
  909.   new.sh = (unsigned char) (score >> 8);
  910.   new.sl = (unsigned char) (score & 0xFF);
  911.  
  912.   for (i = 0; i < frehash; i++)
  913.     {
  914.       fseek(hashfile,
  915.             sizeof(struct fileentry) * ((hashix + 2 * i) & (filesz - 1)),
  916.             SEEK_SET);
  917.       fread(&tmp, sizeof(struct fileentry), 1, hashfile);
  918.       if ((short) tmp.depth <= depth)
  919.         {
  920.           fseek(hashfile,
  921.                 sizeof(struct fileentry) * ((hashix + 2 * i) & (filesz - 1)),
  922.                 SEEK_SET);
  923.           fwrite (&new, sizeof(struct fileentry), 1, hashfile);
  924.           break;
  925.         }
  926.     }
  927. }
  928. #endif /* HASHFILE */
  929. #endif /* ttblsz */
  930.  
  931. void
  932. ZeroRPT (void)
  933. {
  934.   register int side, i;
  935.  
  936.   for (side = white; side <= black; side++)
  937.     for (i = 0; i < 256; i++)
  938.       rpthash[side][i] = 0;
  939. }
  940.  
  941. #define Link(from,to,flag,s) \
  942. {\
  943.    node->f = from; node->t = to;\
  944.      node->reply = 0;\
  945.        node->flags = flag;\
  946.          node->score = s;\
  947.            ++node;\
  948.              ++TrPnt[ply+1];\
  949.              }
  950.  
  951. static inline void
  952. LinkMove (short int ply,
  953.           short int f,
  954.           short int t,
  955.           short int flag,
  956.           short int xside)
  957.  
  958. /*
  959.   Add a move to the tree.  Assign a bonus to order the moves
  960.   as follows:
  961.   1. Principle variation
  962.   2. Capture of last moved piece
  963.   3. Other captures (major pieces first)
  964.   4. Killer moves
  965.   5. "history" killers
  966. */
  967.  
  968. {
  969.   register short s, z;
  970.   unsigned short mv;
  971.   struct leaf far *node;
  972.  
  973.   node = &Tree[TrPnt[ply + 1]];
  974.   mv = (f << 8) | t;
  975.   s = 0;
  976.   if (mv == Swag0)
  977.     s = 2000;
  978.   else if (mv == Swag1)
  979.     s = 60;
  980.   else if (mv == Swag2)
  981.     s = 50;
  982.   else if (mv == Swag3)
  983.     s = 40;
  984.   else if (mv == Swag4)
  985.     s = 30;
  986.   z = (f << 6) | t;
  987.   if (xside == white)
  988.     z |= 0x1000;
  989. /*  s += history[z]; */
  990.   s += *(history+z);
  991.   if (color[t] != neutral)
  992.     {
  993.       if (t == TOsquare)
  994.         s += 500;
  995.       s += value[board[t]] - board[f];
  996.     }
  997.   if (board[f] == pawn)
  998.     if (row (t) == 0 || row (t) == 7)
  999.       {
  1000.         flag |= promote;
  1001.         s += 800;
  1002.         Link (f, t, flag | queen, s - 20000);
  1003.         s -= 200;
  1004.         Link (f, t, flag | knight, s - 20000);
  1005.         s -= 50;
  1006.         Link (f, t, flag | rook, s - 20000);
  1007.         flag |= bishop;
  1008.         s -= 50;
  1009.       }
  1010.     else if (row (t) == 1 || row (t) == 6)
  1011.       {
  1012.         flag |= pwnthrt;
  1013.         s += 600;
  1014.       }
  1015.   Link (f, t, flag, s - 20000);
  1016. }
  1017.  
  1018.  
  1019. static inline void
  1020. GenMoves (short int ply, short int sq, short int side, short int xside)
  1021.  
  1022. /*
  1023.   Generate moves for a piece. The moves are taken from the precalulated
  1024.   array nextpos/nextdir. If the board is free, next move is choosen from
  1025.   nextpos else from nextdir.
  1026. */
  1027.  
  1028. {
  1029.   register short u, piece;
  1030.   unsigned char far *ppos, far *pdir;
  1031.  
  1032.   piece = board[sq];
  1033.   ppos = nextpos+ptype[side][piece]*64*64+sq*64;
  1034.   pdir = nextdir+ptype[side][piece]*64*64+sq*64;
  1035.   if (piece == pawn)
  1036.     {
  1037.       u = ppos[sq];     /* follow no captures thread */
  1038.       if (color[u] == neutral)
  1039.         {
  1040.           LinkMove (ply, sq, u, 0, xside);
  1041.           u = ppos[u];
  1042.           if (color[u] == neutral)
  1043.             LinkMove (ply, sq, u, 0, xside);
  1044.         }
  1045.       u = pdir[sq];     /* follow captures thread */
  1046.       if (color[u] == xside)
  1047.         LinkMove (ply, sq, u, capture, xside);
  1048.       else
  1049.         if (u == epsquare)
  1050.           LinkMove (ply, sq, u, capture | epmask, xside);
  1051.       u = pdir[u];
  1052.       if (color[u] == xside)
  1053.         LinkMove (ply, sq, u, capture, xside);
  1054.       else
  1055.         if (u == epsquare)
  1056.           LinkMove (ply, sq, u, capture | epmask, xside);
  1057.     }
  1058.   else
  1059.     {
  1060.       u = ppos[sq];
  1061.       do
  1062.         {
  1063.           if (color[u] == neutral)
  1064.             {
  1065.               LinkMove (ply, sq, u, 0, xside);
  1066.               u = ppos[u];
  1067.             }
  1068.           else
  1069.             {
  1070.               if (color[u] == xside)
  1071.                 LinkMove (ply, sq, u, capture, xside);
  1072.               u = pdir[u];
  1073.             }
  1074.       } while (u != sq);
  1075.     }
  1076. }
  1077.  
  1078. void
  1079. MoveList (short int side, short int ply)
  1080.  
  1081. /*
  1082.   Fill the array Tree[] with all available moves for side to play. Array
  1083.   TrPnt[ply] contains the index into Tree[] of the first move at a ply.
  1084. */
  1085.  
  1086. {
  1087.   short i, xside, f;
  1088.  
  1089.   xside = otherside[side];
  1090.   TrPnt[ply + 1] = TrPnt[ply];
  1091.   if (PV == 0)
  1092.     Swag0 = killr0[ply];
  1093.   else
  1094.     Swag0 = PV;
  1095.   Swag1 = killr1[ply];
  1096.   Swag2 = killr2[ply];
  1097.   Swag3 = killr3[ply];
  1098.   if (ply > 2)
  1099.     Swag4 = killr1[ply - 2];
  1100.   else
  1101.     Swag4 = 0;
  1102.   for (i = PieceCnt[side]; i >= 0; i--)
  1103.     GenMoves (ply, PieceList[side][i], side, xside);
  1104.   if (!castld[side])
  1105.     {
  1106.       f = PieceList[side][0];
  1107.       if (castle (side, f, f + 2, 0))
  1108.         {
  1109.           LinkMove (ply, f, f + 2, cstlmask, xside);
  1110.         }
  1111.       if (castle (side, f, f - 2, 0))
  1112.         {
  1113.           LinkMove (ply, f, f - 2, cstlmask, xside);
  1114.         }
  1115.     }
  1116. }
  1117.  
  1118. void
  1119. CaptureList (short int side, short int ply)
  1120.  
  1121. /*
  1122.   Fill the array Tree[] with all available cature and promote moves for
  1123.   side to play. Array TrPnt[ply] contains the index into Tree[]
  1124.   of the first move at a ply.
  1125. */
  1126.  
  1127. {
  1128.   short u, sq, xside;
  1129.   struct leaf far *node;
  1130.   unsigned char far *ppos, far *pdir;
  1131.   short i, piece, *PL, r7;
  1132.  
  1133.   xside = otherside[side];
  1134.   TrPnt[ply + 1] = TrPnt[ply];
  1135.   node = &Tree[TrPnt[ply]];
  1136.   r7 = rank7[side];
  1137.   PL = PieceList[side];
  1138.   for (i = 0; i <= PieceCnt[side]; i++)
  1139.     {
  1140.       sq = PL[i];
  1141.       piece = board[sq];
  1142.       if (sweep[piece])
  1143.         {
  1144.           ppos = nextpos+piece*64*64+sq*64;
  1145.           pdir = nextdir+piece*64*64+sq*64;
  1146.           u = ppos[sq];
  1147.           do
  1148.             {
  1149.               if (color[u] == neutral)
  1150.                 u = ppos[u];
  1151.               else
  1152.                 {
  1153.                   if (color[u] == xside)
  1154.                     Link (sq, u, capture,
  1155.                           value[board[u]] + svalue[board[u]] - piece);
  1156.                   u = pdir[u];
  1157.                 }
  1158.           } while (u != sq);
  1159.         }
  1160.       else
  1161.         {
  1162.           pdir = nextdir+ptype[side][piece]*64*64+sq*64;
  1163.           if (piece == pawn && row (sq) == r7)
  1164.             {
  1165.               u = pdir[sq];
  1166.               if (color[u] == xside)
  1167.                 Link (sq, u, capture | promote | queen, valueQ);
  1168.               u = pdir[u];
  1169.               if (color[u] == xside)
  1170.                 Link (sq, u, capture | promote | queen, valueQ);
  1171.               ppos = nextpos+ptype[side][piece]*64*64+sq*64;
  1172.               u = ppos[sq]; /* also generate non capture promote */
  1173.               if (color[u] == neutral)
  1174.                 Link (sq, u, promote | queen, valueQ);
  1175.             }
  1176.           else
  1177.             {
  1178.               u = pdir[sq];
  1179.               do
  1180.                 {
  1181.                   if (color[u] == xside)
  1182.                     Link (sq, u, capture,
  1183.                           value[board[u]] + svalue[board[u]] - piece);
  1184.                   u = pdir[u];
  1185.               } while (u != sq);
  1186.             }
  1187.         }
  1188.     }
  1189. }
  1190.  
  1191.  
  1192. int
  1193. castle (short int side, short int kf, short int kt, short int iop)
  1194.  
  1195. /* Make or Unmake a castling move. */
  1196.  
  1197. {
  1198.   short rf, rt, t0, xside;
  1199.  
  1200.   xside = otherside[side];
  1201.   if (kt > kf)
  1202.     {
  1203.       rf = kf + 3;
  1204.       rt = kt - 1;
  1205.     }
  1206.   else
  1207.     {
  1208.       rf = kf - 4;
  1209.       rt = kt + 1;
  1210.     }
  1211.   if (iop == 0)
  1212.     {
  1213.       if (kf != kingP[side] ||
  1214.           board[kf] != king ||
  1215.           board[rf] != rook ||
  1216.           Mvboard[kf] != 0 ||
  1217.           Mvboard[rf] != 0 ||
  1218.           color[kt] != neutral ||
  1219.           color[rt] != neutral ||
  1220.           color[kt - 1] != neutral ||
  1221.           SqAtakd (kf, xside) ||
  1222.           SqAtakd (kt, xside) ||
  1223.           SqAtakd (rt, xside))
  1224.         return (false);
  1225.     }
  1226.   else
  1227.     {
  1228.       if (iop == 1)
  1229.         {
  1230.           castld[side] = true;
  1231.           Mvboard[kf]++;
  1232.           Mvboard[rf]++;
  1233.         }
  1234.       else
  1235.         {
  1236.           castld[side] = false;
  1237.           Mvboard[kf]--;
  1238.           Mvboard[rf]--;
  1239.           t0 = kt;
  1240.           kt = kf;
  1241.           kf = t0;
  1242.           t0 = rt;
  1243.           rt = rf;
  1244.           rf = t0;
  1245.         }
  1246.       board[kt] = king;
  1247.       color[kt] = side;
  1248.       Pindex[kt] = 0;
  1249.       board[kf] = no_piece;
  1250.       color[kf] = neutral;
  1251.       board[rt] = rook;
  1252.       color[rt] = side;
  1253.       Pindex[rt] = Pindex[rf];
  1254.       board[rf] = no_piece;
  1255.       color[rf] = neutral;
  1256.       PieceList[side][Pindex[kt]] = kt;
  1257.       PieceList[side][Pindex[rt]] = rt;
  1258. #if ttblsz
  1259.       UpdateHashbd (side, king, kf, kt);
  1260.       UpdateHashbd (side, rook, rf, rt);
  1261. #endif /* ttblsz */
  1262.     }
  1263.   return (true);
  1264. }
  1265.  
  1266.  
  1267. static inline void
  1268. EnPassant (short int xside, short int f, short int t, short int iop)
  1269.  
  1270. /*
  1271.   Make or unmake an en passant move.
  1272. */
  1273.  
  1274. {
  1275.   register short l;
  1276.  
  1277.   if (t > f)
  1278.     l = t - 8;
  1279.   else
  1280.     l = t + 8;
  1281.   if (iop == 1)
  1282.     {
  1283.       board[l] = no_piece;
  1284.       color[l] = neutral;
  1285.     }
  1286.   else
  1287.     {
  1288.       board[l] = pawn;
  1289.       color[l] = xside;
  1290.     }
  1291.   InitializeStats ();
  1292. }
  1293.  
  1294.  
  1295. static inline void
  1296. UpdatePieceList (short int side, short int sq, short int iop)
  1297.  
  1298. /*
  1299.   Update the PieceList and Pindex arrays when a piece is captured or when a
  1300.   capture is unmade.
  1301. */
  1302.  
  1303. {
  1304.   register short i;
  1305.   if (iop == 1)
  1306.     {
  1307.       PieceCnt[side]--;
  1308.       for (i = Pindex[sq]; i <= PieceCnt[side]; i++)
  1309.         {
  1310.           PieceList[side][i] = PieceList[side][i + 1];
  1311.           Pindex[PieceList[side][i]] = i;
  1312.         }
  1313.     }
  1314.   else
  1315.     {
  1316.       PieceCnt[side]++;
  1317.       PieceList[side][PieceCnt[side]] = sq;
  1318.       Pindex[sq] = PieceCnt[side];
  1319.     }
  1320. }
  1321.  
  1322. void
  1323. MakeMove (short int side,
  1324.           struct leaf far * node,
  1325.           short int *tempb,
  1326.           short int *tempc,
  1327.           short int *tempsf,
  1328.           short int *tempst,
  1329.           short int *INCscore)
  1330.  
  1331. /*
  1332.   Update Arrays board[], color[], and Pindex[] to reflect the new board
  1333.   position obtained after making the move pointed to by node. Also update
  1334.   miscellaneous stuff that changes when a move is made.
  1335. */
  1336.  
  1337. {
  1338.   short f, t, xside, ct, cf;
  1339.  
  1340.   xside = otherside[side];
  1341.   GameCnt++;
  1342.   f = node->f;
  1343.   t = node->t;
  1344.   epsquare = -1;
  1345.   FROMsquare = f;
  1346.   TOsquare = t;
  1347.   *INCscore = 0;
  1348.   GameList[GameCnt].gmove = (f << 8) | t;
  1349.   if (node->flags & cstlmask)
  1350.     {
  1351.       GameList[GameCnt].piece = no_piece;
  1352.       GameList[GameCnt].color = side;
  1353.       (void) castle (side, f, t, 1);
  1354.     }
  1355.   else
  1356.     {
  1357.       if (!(node->flags & capture) && (board[f] != pawn))
  1358.         rpthash[side][hashkey & 0xFF]++;
  1359.       *tempc = color[t];
  1360.       *tempb = board[t];
  1361.       *tempsf = svalue[f];
  1362.       *tempst = svalue[t];
  1363.       GameList[GameCnt].piece = *tempb;
  1364.       GameList[GameCnt].color = *tempc;
  1365.       if (*tempc != neutral)
  1366.         {
  1367.           UpdatePieceList (*tempc, t, 1);
  1368.           if (*tempb == pawn)
  1369.             --PawnCnt[*tempc][column (t)];
  1370.           if (board[f] == pawn)
  1371.             {
  1372.               --PawnCnt[side][column (f)];
  1373.               ++PawnCnt[side][column (t)];
  1374.               cf = column (f);
  1375.               ct = column (t);
  1376.               if (PawnCnt[side][ct] > 1 + PawnCnt[side][cf])
  1377.                 *INCscore -= 15;
  1378.               else if (PawnCnt[side][ct] < 1 + PawnCnt[side][cf])
  1379.                 *INCscore += 15;
  1380.               else if (ct == 0 || ct == 7 || PawnCnt[side][ct + ct - cf] == 0)
  1381.                 *INCscore -= 15;
  1382.             }
  1383.           mtl[xside] -= value[*tempb];
  1384.           if (*tempb == pawn)
  1385.             pmtl[xside] -= valueP;
  1386. #if ttblsz
  1387.           UpdateHashbd (xside, *tempb, -1, t);
  1388. #endif /* ttblsz */
  1389.           *INCscore += *tempst;
  1390.           Mvboard[t]++;
  1391.         }
  1392.       color[t] = color[f];
  1393.       board[t] = board[f];
  1394.       svalue[t] = svalue[f];
  1395.       Pindex[t] = Pindex[f];
  1396.       PieceList[side][Pindex[t]] = t;
  1397.       color[f] = neutral;
  1398.       board[f] = no_piece;
  1399.       if (board[t] == pawn)
  1400.         if (t - f == 16)
  1401.           epsquare = f + 8;
  1402.         else if (f - t == 16)
  1403.           epsquare = f - 8;
  1404.       if (node->flags & promote)
  1405.         {
  1406.           board[t] = node->flags & pmask;
  1407.           if (board[t] == queen)
  1408.             HasQueen[side]++;
  1409.           else if (board[t] == rook)
  1410.             HasRook[side]++;
  1411.           else if (board[t] == bishop)
  1412.             HasBishop[side]++;
  1413.           else if (board[t] == knight)
  1414.             HasKnight[side]++;
  1415.           --PawnCnt[side][column (t)];
  1416.           mtl[side] += value[board[t]] - valueP;
  1417.           pmtl[side] -= valueP;
  1418. #if ttblsz
  1419.           UpdateHashbd (side, pawn, f, -1);
  1420.           UpdateHashbd (side, board[t], f, -1);
  1421. #endif /* ttblsz */
  1422.           *INCscore -= *tempsf;
  1423.         }
  1424.       if (node->flags & epmask)
  1425.         EnPassant (xside, f, t, 1);
  1426.       else
  1427. #if ttblsz
  1428.         UpdateHashbd (side, board[t], f, t);
  1429. #else
  1430.         /* NOOP */;     
  1431. #endif /* ttblsz */
  1432.       Mvboard[f]++;
  1433.     }
  1434. }
  1435.  
  1436. void
  1437. UnmakeMove (short int side,
  1438.             struct leaf far * node,
  1439.             short int *tempb,
  1440.             short int *tempc,
  1441.             short int *tempsf,
  1442.             short int *tempst)
  1443.  
  1444. /*
  1445.   Take back a move.
  1446. */
  1447.  
  1448. {
  1449.   short f, t, xside;
  1450.  
  1451.   xside = otherside[side];
  1452.   f = node->f;
  1453.   t = node->t;
  1454.   epsquare = -1;
  1455.   GameCnt--;
  1456.   if (node->flags & cstlmask)
  1457.     (void) castle (side, f, t, 2);
  1458.   else
  1459.     {
  1460.       color[f] = color[t];
  1461.       board[f] = board[t];
  1462.       svalue[f] = *tempsf;
  1463.       Pindex[f] = Pindex[t];
  1464.       PieceList[side][Pindex[f]] = f;
  1465.       color[t] = *tempc;
  1466.       board[t] = *tempb;
  1467.       svalue[t] = *tempst;
  1468.       if (node->flags & promote)
  1469.         {
  1470.           board[f] = pawn;
  1471.           ++PawnCnt[side][column (t)];
  1472.           mtl[side] += valueP - value[node->flags & pmask];
  1473.           pmtl[side] += valueP;
  1474. #if ttblsz
  1475.           UpdateHashbd (side, (short) node->flags & pmask, -1, t);
  1476.           UpdateHashbd (side, pawn, -1, t);
  1477. #endif /* ttblsz */
  1478.         }
  1479.       if (*tempc != neutral)
  1480.         {
  1481.           UpdatePieceList (*tempc, t, 2);
  1482.           if (*tempb == pawn)
  1483.             ++PawnCnt[*tempc][column (t)];
  1484.           if (board[f] == pawn)
  1485.             {
  1486.               --PawnCnt[side][column (t)];
  1487.               ++PawnCnt[side][column (f)];
  1488.             }
  1489.           mtl[xside] += value[*tempb];
  1490.           if (*tempb == pawn)
  1491.             pmtl[xside] += valueP;
  1492. #if ttblsz
  1493.           UpdateHashbd (xside, *tempb, -1, t);
  1494. #endif /* ttblsz */
  1495.           Mvboard[t]--;
  1496.         }
  1497.       if (node->flags & epmask)
  1498.         EnPassant (xside, f, t, 2);
  1499.       else
  1500. #if ttblsz
  1501.         UpdateHashbd (side, board[f], f, t);
  1502. #else
  1503.       /* NOOP */;
  1504. #endif /* ttblsz */
  1505.       Mvboard[f]--;
  1506.       if (!(node->flags & capture) && (board[f] != pawn))
  1507.         rpthash[side][hashkey & 0xFF]--;
  1508.     }
  1509. }
  1510.  
  1511.  
  1512. void
  1513. InitializeStats (void)
  1514.  
  1515. /*
  1516.   Scan thru the board seeing what's on each square. If a piece is found,
  1517.   update the variables PieceCnt, PawnCnt, Pindex and PieceList. Also
  1518.   determine the material for each side and set the hashkey and hashbd
  1519.   variables to represent the current board position. Array
  1520.   PieceList[side][indx] contains the location of all the pieces of either
  1521.   side. Array Pindex[sq] contains the indx into PieceList for a given
  1522.   square.
  1523. */
  1524.  
  1525. {
  1526.   short i, sq;
  1527.   
  1528.   epsquare = -1;
  1529.   for (i = 0; i < 8; i++)
  1530.     PawnCnt[white][i] = PawnCnt[black][i] = 0;
  1531.   mtl[white] = mtl[black] = pmtl[white] = pmtl[black] = 0;
  1532.   PieceCnt[white] = PieceCnt[black] = 0;
  1533. #if ttblsz
  1534.   hashbd = hashkey = 0;
  1535. #endif /* ttblsz */
  1536.   for (sq = 0; sq < 64; sq++)
  1537.     if (color[sq] != neutral)
  1538.       {
  1539.         mtl[color[sq]] += value[board[sq]];
  1540.         if (board[sq] == pawn)
  1541.           {
  1542.             pmtl[color[sq]] += valueP;
  1543.             ++PawnCnt[color[sq]][column (sq)];
  1544.           }
  1545.         if (board[sq] == king)
  1546.           Pindex[sq] = 0;
  1547.         else
  1548.           Pindex[sq] = ++PieceCnt[color[sq]];
  1549.         PieceList[color[sq]][Pindex[sq]] = sq;
  1550. #if ttblsz
  1551.         hashbd ^= (hashcode+color[sq]*7*64+board[sq]*64+sq)->bd;
  1552.         hashkey ^= (hashcode+color[sq]*7*64+board[sq]*64+sq)->key;
  1553. #endif /* ttblsz */
  1554.       }
  1555. }
  1556.  
  1557.  
  1558. int
  1559. SqAtakd (short int sq, short int side)
  1560.  
  1561. /*
  1562.   See if any piece with color 'side' ataks sq.  First check pawns then Queen,
  1563.   Bishop, Rook and King and last Knight.
  1564. */
  1565.  
  1566. {
  1567.   register short u;
  1568.   unsigned char far *ppos, far *pdir;
  1569.   short xside;
  1570.  
  1571.   xside = otherside[side];
  1572.   pdir = nextdir+ptype[xside][pawn]*64*64+sq*64;
  1573.   u = pdir[sq];         /* follow captures thread */
  1574.   if (u != sq)
  1575.     {
  1576.       if (board[u] == pawn && color[u] == side)
  1577.         return (true);
  1578.       u = pdir[u];
  1579.       if (u != sq && board[u] == pawn && color[u] == side)
  1580.         return (true);
  1581.     }
  1582.   /* king capture */
  1583.   if (distance (sq, PieceList[side][0]) == 1)
  1584.     return (true);
  1585.   /* try a queen bishop capture */
  1586.   ppos = nextpos+bishop*64*64+sq*64;
  1587.   pdir = nextdir+bishop*64*64+sq*64;
  1588.   u = ppos[sq];
  1589.   do
  1590.     {
  1591.       if (color[u] == neutral)
  1592.         u = ppos[u];
  1593.       else
  1594.         {
  1595.           if (color[u] == side &&
  1596.               (board[u] == queen || board[u] == bishop))
  1597.             return (true);
  1598.           u = pdir[u];
  1599.         }
  1600.   } while (u != sq);
  1601.   /* try a queen rook capture */
  1602.   ppos = nextpos+rook*64*64+sq*64;
  1603.   pdir = nextdir+rook*64*64+sq*64;
  1604.   u = ppos[sq];
  1605.   do
  1606.     {
  1607.       if (color[u] == neutral)
  1608.         u = ppos[u];
  1609.       else
  1610.         {
  1611.           if (color[u] == side &&
  1612.               (board[u] == queen || board[u] == rook))
  1613.             return (true);
  1614.           u = pdir[u];
  1615.         }
  1616.   } while (u != sq);
  1617.   /* try a knight capture */
  1618.   pdir = nextdir+knight*64*64+sq*64;
  1619.   u = pdir[sq];
  1620.   do
  1621.     {
  1622.       if (color[u] == side && board[u] == knight)
  1623.         return (true);
  1624.       u = pdir[u];
  1625.   } while (u != sq);
  1626.   return (false);
  1627. }
  1628.  
  1629. void
  1630. ataks (short int side, short int *a)
  1631.  
  1632. /*
  1633.   Fill array atak[][] with info about ataks to a square.  Bits 8-15 are set
  1634.   if the piece (king..pawn) ataks the square.  Bits 0-7 contain a count of
  1635.   total ataks to the square.
  1636. */
  1637.  
  1638. {
  1639.   short u, c, sq;
  1640.   unsigned char far *ppos, far *pdir;
  1641.   short i, piece, *PL;
  1642.  
  1643. #ifdef NOMEMSET
  1644.   for (u = 64; u; a[--u] = 0) ;
  1645. #else
  1646.   memset ((char *) a, 0, 64 * sizeof (a[0]));
  1647. #endif /* NOMEMSET */
  1648.   PL = PieceList[side];
  1649.   for (i = PieceCnt[side]; i >= 0; i--)
  1650.     {
  1651.       sq = PL[i];
  1652.       piece = board[sq];
  1653.       c = control[piece];
  1654.       if (sweep[piece])
  1655.         {
  1656.           ppos = nextpos+piece*64*64+sq*64;
  1657.           pdir = nextdir+piece*64*64+sq*64;
  1658.           u = ppos[sq];
  1659.           do
  1660.             {
  1661.               a[u] = ++a[u] | c;
  1662.               u = (color[u] == neutral) ? ppos[u] : pdir[u];
  1663.           } while (u != sq);
  1664.         }
  1665.       else
  1666.         {
  1667.           pdir = nextdir+ptype[side][piece]*64*64+sq*64;
  1668.           u = pdir[sq]; /* follow captures thread for pawns */
  1669.           do
  1670.             {
  1671.               a[u] = ++a[u] | c;
  1672.               u = pdir[u];
  1673.           } while (u != sq);
  1674.         }
  1675.     }
  1676. }
  1677.  
  1678.